package org.nobody.mallb2c.mallware.listener;

import com.alibaba.fastjson.TypeReference;
import com.rabbitmq.client.Channel;
import org.nobody.common.to.mq.OrderTo;
import org.nobody.common.to.mq.StockDetailTo;
import org.nobody.common.to.mq.StockLockedTo;
import org.nobody.common.utils.R;
import org.nobody.mallb2c.mallware.entity.WareOrderTaskDetailEntity;
import org.nobody.mallb2c.mallware.entity.WareOrderTaskEntity;
import org.nobody.mallb2c.mallware.feign.OrderFeignService;
import org.nobody.mallb2c.mallware.service.WareOrderTaskDetailService;
import org.nobody.mallb2c.mallware.service.WareOrderTaskService;
import org.nobody.mallb2c.mallware.service.WareSkuService;
import org.nobody.mallb2c.mallware.vo.OrderVo;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * @author 3489309323@qq.com
 * @create 2020-09-25-21:28
 */
@Service
@RabbitListener(queues = "stock.release.stock.queue")
public class StockReleaseListener {
  @Autowired
  WareSkuService wareSkuService;

  @Autowired
  WareOrderTaskService orderTaskService;

  @Autowired
  WareOrderTaskDetailService orderTaskDetailService;

  @Autowired
  OrderFeignService orderFeignService;

  /**
   *
   * 1、下订单成功,库存锁定成功,但是接下来的业务调用失败,导致订单回滚,之前锁定的库存就要解锁
   * 2、锁库存本身失败(库存不够)
   *
   * 解锁库存可能失败,需要使用手动ack机制,确保解锁一定成功
   *
   * 注意：
   *    因为这里是接受消息自动解锁, 故无需验证用户是否登录,  也没法验证(因为消息是MQ直接发往后台这里的,不可能携带cookie撒的,没有经过用户)
   *    而这里会调用 orderFeignService.getOrderStatus(orderSn), 故需要在order服务中对此接口放行
   *
   */


  /**
   * 被动解锁(由stock-event-exchange触发)
   */
  //  @RabbitHandler
//  public void handleStockLockedRelease(StockLockedTo to, Message message, Channel channel) throws IOException {
//    System.out.println("收到解锁库存的消息");
//    try {
//      StockDetailTo detail = to.getDetail();
//      Long detailId = detail.getId();
//
//      WareOrderTaskDetailEntity byId = orderTaskDetailService.getById(detailId); //mq发来实体并不一定在数据库里有(可能回滚了)
//      if(byId!=null){
//        //1、没有这个订单,必须解锁
//        //2、有这个订单,看订单状态
//        //   已取消->解锁库存
//        //   没取消->不能解锁
//
//        Long id = to.getId();
//        WareOrderTaskEntity taskEntity = orderTaskService.getById(id);
//        String orderSn = taskEntity.getOrderSn();
//        R r = orderFeignService.getOrderStatus(orderSn);
//        if (r.getCode() == 0) {
//          //订单数据返回成功
//          OrderVo data = r.getData(new TypeReference<OrderVo>() {});
//
//          //下订单因为非库存因素而回滚了(此时库存已锁定),即没有这个订单
//          // 或  订单已经被取消,即订单状态为4
//          if (data == null || data.getStatus() == 4/*订单已取消、关闭*/) {
//            wareSkuService.unLockStock(detail.getSkuId(),detail.getWareId(),detail.getSkuNum(),detailId);
//          }
//          channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
//
//        }else { //feign调用失败, 应该再次重试解锁消息的推送
//          channel.basicReject(message.getMessageProperties().getDeliveryTag(), true/*←重新入队*/);
//        }
//
//      }else{
//        //没有查询到数据库关于这个订单的锁定库存信息(说明已经回滚了)
//        //这种情况无需解锁
//        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
//      }
//    }catch (Exception e){
//      System.out.println("handleStockLockedRelease错误: " + e.getMessage());
//      channel.basicReject(message.getMessageProperties().getDeliveryTag(), true/*←重新入队*/);
//    }
//  }

  @RabbitHandler
  public void handleStockLockedRelease(StockLockedTo to, Message message, Channel channel) throws IOException {
    System.out.println("收到解锁库存的消息~~~~~~~~~~~~~");
    try {
      //当前消息是否是重新派发的↓
      //Boolean redelivered = message.getMessageProperties().getRedelivered();

      wareSkuService.unlockStock(to);

      channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

    }catch (Exception e){
      System.out.println("handleStockLockedRelease错误: " + e.getMessage());
      channel.basicReject(message.getMessageProperties().getDeliveryTag(), true/*←重新入队*/);
    }
  }


  /**
   * 主动解锁(由order-event-exchange触发)
   *
   * 防止因为服务器卡顿原因 库存解锁时订单状态还没有定时变成取消状态
   * 导致库存永远死锁的问题
   *
   */
  @RabbitHandler
  public void handleOrderCloseRelease(OrderTo orderTo, Message message, Channel channel) throws IOException {
    System.out.println("订单关闭,准备解锁库存 ...");
    try {
      wareSkuService.unlockStock(orderTo);
      channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);
    }catch (Exception e){
      System.out.println("handleOrderCloseRelease错误: " + e.getMessage());
      channel.basicReject(message.getMessageProperties().getDeliveryTag(), true/*←重新入队*/);
    }
  }
}
